package com.sz.admin.datainfo.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import com.sz.admin.datainfo.mapper.DriverUserMapper;
import com.sz.admin.vehicleinfo.mapper.VehicleInfoMapper;
import com.sz.admin.vehicleschedule.mapper.VehicleScheduleMapper;
import com.sz.admin.system.mapper.SysMonitorFileRecordMapper;
import com.sz.admin.datainfo.pojo.dto.DriverUserCreateDTO;
import com.sz.admin.datainfo.pojo.dto.DriverUserUpdateDTO;
import com.sz.admin.datainfo.pojo.dto.DriverUserListDTO;
import com.sz.admin.datainfo.pojo.dto.DriverVehicleQueryDTO;
import com.sz.admin.datainfo.pojo.po.DriverUser;
import com.sz.admin.datainfo.pojo.vo.DriverUserVO;
import com.sz.admin.datainfo.pojo.vo.DriverVehicleInfoVO;
import com.sz.admin.datainfo.service.DriverUserService;
import com.sz.admin.system.pojo.po.SysMonitorFileRecord;
import com.sz.admin.system.service.SysUserRoleService;
import com.sz.core.common.entity.PageResult;
import com.sz.core.common.entity.SelectIdsDTO;
import com.sz.core.common.enums.CommonResponseEnum;
import com.sz.core.util.BeanCopyUtils;
import com.sz.core.util.SysConfigUtils;
import com.mybatisflex.core.paginate.Page;
import com.sz.core.util.PageUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.ArrayList;
import java.util.function.Consumer;

import static com.sz.admin.vehicleinfo.pojo.po.table.VehicleInfoTableDef.VEHICLE_INFO;
import static com.sz.admin.vehicleschedule.pojo.po.table.VehicleScheduleTableDef.VEHICLE_SCHEDULE;
import static com.sz.admin.system.pojo.po.table.SysDeptTableDef.SYS_DEPT;
import static com.mybatisflex.core.query.QueryMethods.*;

/**
 * <p>
 * 司机用户 服务实现类
 * </p>
 *
 * @author sz-admin
 * @since 2025-09-12
 */
@Service
@RequiredArgsConstructor
public class DriverUserServiceImpl implements DriverUserService {

    private final DriverUserMapper driverUserMapper;
    
    @Autowired
    private VehicleInfoMapper vehicleInfoMapper;
    
    @Autowired
    private VehicleScheduleMapper vehicleScheduleMapper;
    
    @Autowired
    private SysMonitorFileRecordMapper sysMonitorFileRecordMapper;
    
    @Autowired
    private SysUserRoleService sysUserRoleService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(DriverUserCreateDTO dto) {
        // 检查用户名是否已存在
        int usernameExists = driverUserMapper.checkUsernameExists(dto.getUsername(), null);
        CommonResponseEnum.USERNAME_EXISTS.assertTrue(usernameExists > 0);

        // 检查手机号是否已存在
        if (dto.getPhone() != null && !dto.getPhone().isEmpty()) {
            int phoneExists = driverUserMapper.checkPhoneExists(dto.getPhone(), null);
            CommonResponseEnum.EXISTS.message("手机号已存在").assertTrue(phoneExists > 0);
        }

        DriverUser driverUser = BeanCopyUtils.copy(dto, DriverUser.class);
    
        // 设置默认值
        driverUser.setUserTagCd("1001003"); // 司机标签
        driverUser.setAccountStatusCd(dto.getAccountStatusCd() != null ? dto.getAccountStatusCd() : "1000001"); // 默认启用
        driverUser.setDelFlag("F");
        driverUser.setCreateTime(LocalDateTime.now());
        driverUser.setUpdateTime(LocalDateTime.now());
    
        // 密码处理：如果没有传递密码，读取配置，设置默认密码
        String password = dto.getPwd();
        if (password == null || password.isEmpty()) {
            password = getInitPassword();
        }
        String encodePwd = getEncoderPwd(password);
        driverUser.setPwd(encodePwd);
    
        // 设置昵称默认为用户名
        if (driverUser.getNickname() == null || driverUser.getNickname().isEmpty()) {
            driverUser.setNickname(driverUser.getUsername());
        }

        int result = driverUserMapper.insert(driverUser);
        CommonResponseEnum.SAVE_FAIL.assertTrue(result <= 0);
        
        // 设置用户角色为司机角色 (role_id = 7)
        sysUserRoleService.syncUserRolec(driverUser.getId(), 7L);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(DriverUserUpdateDTO dto) {
        // 检查记录是否存在
        DriverUserVO existingUser = driverUserMapper.selectById(dto.getId());
        CommonResponseEnum.INVALID_ID.assertNull(existingUser);

        // 检查用户名是否已存在（排除当前记录）
        if (dto.getUsername() != null && !dto.getUsername().isEmpty()) {
            int usernameExists = driverUserMapper.checkUsernameExists(dto.getUsername(), dto.getId());
            CommonResponseEnum.USERNAME_EXISTS.assertTrue(usernameExists > 0);
        }

        // 检查手机号是否已存在（排除当前记录）
        if (dto.getPhone() != null && !dto.getPhone().isEmpty()) {
            int phoneExists = driverUserMapper.checkPhoneExists(dto.getPhone(), dto.getId());
            CommonResponseEnum.EXISTS.message("手机号已存在").assertTrue(phoneExists > 0);
        }

        DriverUser driverUser = BeanCopyUtils.copy(dto, DriverUser.class);
        driverUser.setUpdateTime(LocalDateTime.now());

        int result = driverUserMapper.updateById(driverUser);
        CommonResponseEnum.UPDATE_FAIL.assertTrue(result <= 0);
    }

    @Override
    public PageResult<DriverUserVO> page(DriverUserListDTO dto) {
        PageHelper.startPage(dto.getPage(), dto.getLimit());
        // Ensure we're only querying non-deleted drivers
        List<DriverUserVO> list = driverUserMapper.selectPageList(dto);
        PageInfo<DriverUserVO> pageInfo = new PageInfo<>(list);
        
        // Calculate total pages
        long totalPages = (pageInfo.getTotal() + dto.getLimit() - 1) / dto.getLimit();
        
        return new PageResult<>(
                dto.getPage(),
                dto.getLimit(), 
                totalPages,
                pageInfo.getTotal(),
                list
        );
    }

    @Override
    public List<DriverUserVO> list(DriverUserListDTO dto) {
        // Ensure we're only querying non-deleted drivers
        return driverUserMapper.selectList(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(SelectIdsDTO dto) {
        CommonResponseEnum.INVALID_ID.assertTrue(dto.getIds() == null || dto.getIds().isEmpty());
        
        @SuppressWarnings("unchecked")
        int result = driverUserMapper.deleteByIds((List<Long>) dto.getIds());
        CommonResponseEnum.DELETE_FAIL.assertTrue(result > 0);
    }

    @Override
    public DriverUserVO detail(Long id) {
        DriverUserVO driverUserVO = driverUserMapper.selectById(id);
        CommonResponseEnum.INVALID_ID.assertNull(driverUserVO);
        return driverUserVO;
    }

    @Override
    public DriverUserVO selectByPhone(String phone) {
        return driverUserMapper.selectByPhone(phone);
    }

    @Override
    public com.sz.admin.datainfo.pojo.po.DriverUser selectByPhoneWithPassword(String phone) {
        return driverUserMapper.selectByPhoneWithPassword(phone);
    }

    @Override
    public PageResult<DriverVehicleInfoVO> queryDriverVehicleInfo(DriverVehicleQueryDTO dto) {
        Long driverId = dto.getDriverId();
        CommonResponseEnum.INVALID_ID.assertNull(driverId);
        
        // 构建分页查询
        Page<DriverVehicleInfoVO> page = PageUtils.getPage(dto);
        
        // 查询司机关联的车辆信息
        QueryWrapper vehicleQuery = QueryWrapper.create()
                .select(VEHICLE_INFO.ID.as("vehicleId"),
                        VEHICLE_INFO.VEHICLE_NUMBER.as("vehicleNumber"),
                        VEHICLE_INFO.TITLE.as("vehicleTitle"),
                        VEHICLE_INFO.DEPARTMENT_ID.as("departmentId"),
                        VEHICLE_INFO.SCHEDULE_ID.as("scheduleId"),
                        VEHICLE_INFO.USER_ID1.as("userId1"),
                        VEHICLE_INFO.USER_ID2.as("userId2"),
                        VEHICLE_INFO.USER_ID3.as("userId3"),
                        SYS_DEPT.NAME.as("departmentName"),
                        VEHICLE_SCHEDULE.TITLE.as("scheduleName"),
                        VEHICLE_SCHEDULE.TIME1.as("scheduleTime1"),
                        VEHICLE_SCHEDULE.TIME2.as("scheduleTime2"),
                        VEHICLE_SCHEDULE.TIME3.as("scheduleTime3"),
                        VEHICLE_SCHEDULE.SCHEDULE_TYPE.as("scheduleType")
                )
                .from(VEHICLE_INFO)
                .leftJoin(SYS_DEPT).on(SYS_DEPT.ID.eq(VEHICLE_INFO.DEPARTMENT_ID))
                .leftJoin(VEHICLE_SCHEDULE).on(VEHICLE_SCHEDULE.ID.eq(VEHICLE_INFO.SCHEDULE_ID))
                .where(VEHICLE_INFO.USER_ID1.eq(driverId)
                        .or(VEHICLE_INFO.USER_ID2.eq(driverId))
                        .or(VEHICLE_INFO.USER_ID3.eq(driverId)))
                .and(VEHICLE_INFO.DEL_FLAG.eq("F"));
        
        // 执行分页查询
        Page<DriverVehicleInfoVO> resultPage = vehicleInfoMapper.paginateAs(page, vehicleQuery, DriverVehicleInfoVO.class);
        
        // 为每个车辆查询监控文件记录
        for (DriverVehicleInfoVO vehicleInfo : resultPage.getRecords()) {
            if (vehicleInfo.getVehicleNumber() != null) {
                QueryWrapper recordQuery = QueryWrapper.create()
                        .select("sys_monitor_file_record.id", "sys_monitor_file_record.monitor_id", "sys_monitor_file_record.original_filename", "sys_monitor_file_record.new_filename", "sys_monitor_file_record.file_url",
                                "sys_monitor_file_record.process_status", "sys_monitor_file_record.process_time", "sys_monitor_file_record.file_tag as dtuNumber", "sys_monitor_file_record.car_number", "sys_monitor_file_record.car_number_res", "sys_monitor_file_record.create_time",
                                "dtu.dtu_number", "dtu.vehicle_id", "v.department_id")
                        .from(SysMonitorFileRecord.class)
                        .leftJoin("dtu_info").as("dtu").on("dtu.dtu_number = file_tag")
                        .leftJoin("vehicle_info").as("v").on("v.id = dtu.vehicle_id")
                        .where(SysMonitorFileRecord::getCarNumber).eq(vehicleInfo.getVehicleNumber())
                        .and(SysMonitorFileRecord::getDelFlag).eq("F")
                        .and(SysMonitorFileRecord::getProcessStatus).eq("1"); // 只查询成功处理的记录
                
                // 添加部门ID过滤条件
                if (vehicleInfo.getDepartmentId() != null) {
                    recordQuery.and(column("v.department_id").eq(vehicleInfo.getDepartmentId()));
                }
                
                // 不管是否指定了时间范围，都根据排班时间进行过滤
                if (vehicleInfo.getScheduleTime1() != null || vehicleInfo.getScheduleTime2() != null || vehicleInfo.getScheduleTime3() != null) {
                    // 根据排班类型和用户ID应用不同的时间过滤规则（不使用时间范围参数）
                    addScheduleTimeFilterWithoutRange(recordQuery, 
                                    vehicleInfo.getScheduleTime1(), vehicleInfo.getScheduleTime2(), vehicleInfo.getScheduleTime3(),
                                    vehicleInfo.getScheduleType(), driverId, 
                                    vehicleInfo.getUserId1(), vehicleInfo.getUserId2(), vehicleInfo.getUserId3());
                }
                
                recordQuery.orderBy(SysMonitorFileRecord::getCreateTime, false);
                
                List<DriverVehicleInfoVO.MonitorFileRecordInfoVO> records = sysMonitorFileRecordMapper.selectListByQueryAs(
                        recordQuery, DriverVehicleInfoVO.MonitorFileRecordInfoVO.class);
                
                vehicleInfo.setMonitorFileRecords(records);
                vehicleInfo.setMonitorFileRecordCount(records.size());
            } else {
                vehicleInfo.setMonitorFileRecords(new ArrayList<>());
                vehicleInfo.setMonitorFileRecordCount(0);
            }
        }
        
        return PageUtils.getPageResult(resultPage);
    }

    /**
     * 密码加密
     */
    private String getEncoderPwd(String pwd) {
        return BCrypt.hashpw(pwd, BCrypt.gensalt(10));
    }

    /**
     * 获取默认密码
     */
    private String getInitPassword() {
        return SysConfigUtils.getConfValue("sys.user.initPwd");
    }

    /**
     * 根据排班类型和用户ID过滤监控记录
     * @param query 查询条件
     * @param startTime 查询开始时间
     * @param endTime 查询结束时间
     * @param scheduleTime1 排班时间1
     * @param scheduleTime2 排班时间2
     * @param scheduleTime3 排班时间3
     * @param scheduleType 排班类型
     * @param driverId 司机ID
     * @param userId1 用户ID1
     * @param userId2 用户ID2
     * @param userId3 用户ID3
     */
    private void addScheduleTimeFilter(QueryWrapper query, LocalDateTime startTime, LocalDateTime endTime,
                                       LocalTime scheduleTime1, LocalTime scheduleTime2, LocalTime scheduleTime3,
                                       String scheduleType, Long driverId, Long userId1, Long userId2, Long userId3) {
        
        // 如果没有指定排班类型或者排班类型为2001001，则查询所有时间区间的数据
        if (scheduleType == null || "2001001".equals(scheduleType)) {
            // 查询所有时间区间的数据，只使用基本的时间范围过滤
            query.and(SysMonitorFileRecord::getCreateTime).between(startTime, endTime);
            return;
        }
        
        // 根据排班类型应用不同的过滤规则
        if ("2001002".equals(scheduleType)) {
            // 排班类型2001002的规则
            if (driverId.equals(userId1)) {
                // driverId = userId1，查询time1-time2区间的数据
                if (scheduleTime1 != null && scheduleTime2 != null) {
                    // 添加时间区间过滤条件（只比较时间部分，忽略日期）
                    addTimeRangeFilter(query, scheduleTime1, scheduleTime2);
                } else {
                    query.and(SysMonitorFileRecord::getCreateTime).between(startTime, endTime);
                }
            } else if (driverId.equals(userId2)) {
                // driverId = userId2，查询time2-time1区间的数据（跨天）
                if (scheduleTime2 != null && scheduleTime1 != null) {
                    // 添加跨天时间区间过滤条件（只比较时间部分，忽略日期）
                    addCrossDayTimeRangeFilter(query, scheduleTime2, scheduleTime1);
                } else {
                    query.and(SysMonitorFileRecord::getCreateTime).between(startTime, endTime);
                }
            } else {
                // 其他情况使用基本的时间范围过滤
                query.and(SysMonitorFileRecord::getCreateTime).between(startTime, endTime);
            }
        } else if ("2001003".equals(scheduleType)) {
            // 排班类型2001003的规则
            if (driverId.equals(userId1)) {
                // driverId = userId1，查询time1-time2区间的数据
                if (scheduleTime1 != null && scheduleTime2 != null) {
                    // 添加时间区间过滤条件（只比较时间部分，忽略日期）
                    addTimeRangeFilter(query, scheduleTime1, scheduleTime2);
                } else {
                    query.and(SysMonitorFileRecord::getCreateTime).between(startTime, endTime);
                }
            } else if (driverId.equals(userId2)) {
                // driverId = userId2，查询time2-time3区间的数据
                if (scheduleTime2 != null && scheduleTime3 != null) {
                    // 添加时间区间过滤条件（只比较时间部分，忽略日期）
                    addTimeRangeFilter(query, scheduleTime2, scheduleTime3);
                } else {
                    query.and(SysMonitorFileRecord::getCreateTime).between(startTime, endTime);
                }
            } else if (driverId.equals(userId3)) {
                // driverId = userId3，查询time3-time1区间的数据（跨天）
                if (scheduleTime3 != null && scheduleTime1 != null) {
                    // 添加跨天时间区间过滤条件（只比较时间部分，忽略日期）
                    addCrossDayTimeRangeFilter(query, scheduleTime3, scheduleTime1);
                } else {
                    query.and(SysMonitorFileRecord::getCreateTime).between(startTime, endTime);
                }
            } else {
                // 其他情况使用基本的时间范围过滤
                query.and(SysMonitorFileRecord::getCreateTime).between(startTime, endTime);
            }
        } else {
            // 其他排班类型使用基本的时间范围过滤
            query.and(SysMonitorFileRecord::getCreateTime).between(startTime, endTime);
        }
    }
    
    /**
     * 添加时间区间过滤条件（同一天内）
     * @param query 查询条件
     * @param startTime 开始时间
     * @param endTime 结束时间
     */
    private void addTimeRangeFilter(QueryWrapper query, LocalTime startTime, LocalTime endTime) {
        // 使用数据库函数提取时间部分进行比较
        // 这里使用MySQL的TIME()函数提取时间部分
        QueryCondition condition = column("TIME(sys_monitor_file_record.create_time)").ge(startTime)
                .and(column("TIME(sys_monitor_file_record.create_time)").le(endTime));
        query.and(condition);
    }
    
    /**
     * 添加跨天时间区间过滤条件
     * @param query 查询条件
     * @param startTime 开始时间
     * @param endTime 结束时间（第二天的时间）
     */
    private void addCrossDayTimeRangeFilter(QueryWrapper query, LocalTime startTime, LocalTime endTime) {
        // 跨天时间区间过滤：(TIME(sys_monitor_file_record.create_time) >= startTime) OR (TIME(sys_monitor_file_record.create_time) <= endTime)
        // 对于跨天情况，我们需要查询在startTime之后或endTime之前的时间记录
        QueryCondition condition = column("TIME(sys_monitor_file_record.create_time)").ge(startTime)
                .or(column("TIME(sys_monitor_file_record.create_time)").le(endTime));
        query.and(condition);
    }
    
    /**
     * 根据排班类型和用户ID过滤监控记录（不使用时间范围参数，只根据排班时间过滤）
     * @param query 查询条件
     * @param scheduleTime1 排班时间1
     * @param scheduleTime2 排班时间2
     * @param scheduleTime3 排班时间3
     * @param scheduleType 排班类型
     * @param driverId 司机ID
     * @param userId1 用户ID1
     * @param userId2 用户ID2
     * @param userId3 用户ID3
     */
    private void addScheduleTimeFilterWithoutRange(QueryWrapper query,
                                   LocalTime scheduleTime1, LocalTime scheduleTime2, LocalTime scheduleTime3,
                                   String scheduleType, Long driverId, Long userId1, Long userId2, Long userId3) {
    
        // 如果没有指定排班类型或者排班类型为2001001，则不应用时间过滤
        if (scheduleType == null || "2001001".equals(scheduleType)) {
            // 不应用任何时间过滤
            return;
        }
        
        // 根据排班类型应用不同的过滤规则
        if ("2001002".equals(scheduleType)) {
            // 排班类型2001002的规则
            if (driverId.equals(userId1)) {
                // driverId = userId1，查询time1-time2区间的数据
                if (scheduleTime1 != null && scheduleTime2 != null) {
                    // 添加时间区间过滤条件（只比较时间部分，忽略日期）
                    addTimeRangeFilter(query, scheduleTime1, scheduleTime2);
                }
            } else if (driverId.equals(userId2)) {
                // driverId = userId2，查询time2-time1区间的数据（跨天）
                if (scheduleTime2 != null && scheduleTime1 != null) {
                    // 添加跨天时间区间过滤条件（只比较时间部分，忽略日期）
                    addCrossDayTimeRangeFilter(query, scheduleTime2, scheduleTime1);
                }
            }
        } else if ("2001003".equals(scheduleType)) {
            // 排班类型2001003的规则
            if (driverId.equals(userId1)) {
                // driverId = userId1，查询time1-time2区间的数据
                if (scheduleTime1 != null && scheduleTime2 != null) {
                    // 添加时间区间过滤条件（只比较时间部分，忽略日期）
                    addTimeRangeFilter(query, scheduleTime1, scheduleTime2);
                }
            } else if (driverId.equals(userId2)) {
                // driverId = userId2，查询time2-time3区间的数据
                if (scheduleTime2 != null && scheduleTime3 != null) {
                    // 添加时间区间过滤条件（只比较时间部分，忽略日期）
                    addTimeRangeFilter(query, scheduleTime2, scheduleTime3);
                }
            } else if (driverId.equals(userId3)) {
                // driverId = userId3，查询time3-time1区间的数据（跨天）
                if (scheduleTime3 != null && scheduleTime1 != null) {
                    // 添加跨天时间区间过滤条件（只比较时间部分，忽略日期）
                    addCrossDayTimeRangeFilter(query, scheduleTime3, scheduleTime1);
                }
            }
        }
    }
}